#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"gui.h"

int gui_signal_create(gui_spirit_t *spirit,const char *name)
{
    gui_signal_t *sig=(gui_signal_t*)malloc(sizeof(gui_signal_t));
    if(!sig)
        return -1;
    sig->callback=NULL;
    sig->calldata=NULL;
    memset(sig->name,0,GUI_SIGNAL_NAME_LEN+1);
    strncpy(sig->name,name,GUI_SIGNAL_NAME_LEN);
    list_add_tail(&sig->list,&spirit->signal_list);
    return 0;
}

int gui_signal_destroy(gui_spirit_t *spirit,const char *name)
{
    if(!spirit)
        return -1;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if(!strcmp(sig->name,name))
        {
            list_del(&sig->list);
            free(sig);
            return 0;
        }
    }
    return -1;
}

int gui_signal_destroy_all(gui_spirit_t *spirit)
{
    if(!spirit)
        return -1;

    gui_signal_t *sig,*next;
    list_traversal_all_owner_to_next_safe(sig,next,&spirit->signal_list,list)
    {
        list_del(&sig->list);
        free(sig);
    }
    return 0;
}

int gui_signal_connect(gui_spirit_t *spirit,const char *name,void *func,void *data)
{
    if(!spirit||!name)
        return -1;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if(!strcmp(sig->name,name))
        {
            sig->callback=func;
            sig->calldata=data;
            return 0;
        }
    }
    return -1;
}

bool gui_signal_emit_by_name(gui_spirit_t *spirit,const char *name)
{
    if(!spirit||!name)
        return false;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if(!strcmp(sig->name,name))
        {   
            if(sig->callback)
            {
                gui_callback_t callback=(gui_callback_t)sig->callback;
                return callback(spirit,sig->calldata);            
            }
            break;
        }
    }
    return 0;
}

bool gui_signal_emit_arg(gui_spirit_t *spirit,const char *name,void *arg)
{
    if(!spirit||!name)
        return -1;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if(!strcmp(sig->name,name))
        {
            if(sig->callback)
            {
                gui_callback_event_t callback=(gui_callback_event_t)sig->callback;
                return callback(spirit,arg,sig->calldata);
            }
            break;
        }
    }
    return 0;
}

int gui_spirit_emit(gui_spirit_t *spirit,int signal_id)
{
    if(!spirit)
        return -1;
    int id=0;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if(id++==signal_id)
        {
            if(sig->callback)
            {
                gui_callback_t callback=(gui_callback_t)sig->callback;
                return callback(spirit,sig->calldata);
            }
            break;
        }
    }
    return 0;
}

int gui_signal_available(gui_spirit_t *spirit,char *name)
{
     if(!spirit||!name)
        return -1;
    gui_signal_t *sig;
    list_traversal_all_owner_to_next(sig,&spirit->signal_list,list)
    {
        if((!strcmp(sig->name,name))&&sig->callback)
        {
            return 1;
        }
    }
    dprintf("[gui signal] no found signal %s\n",name);
    return 0;
}